package com.googlecode.jtoy.patterns.proxy.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import com.googlecode.jtoy.patterns.proxy.Advice;

/**
 * CGLIB代理
 * 
 * @author shangxj
 * @date Jun 19, 2011 12:19:14 AM
 */
public class CglibProxyFactory implements MethodInterceptor {

	private Advice advice;

	private Object target;

	public CglibProxyFactory(Advice advice) {

		this.advice = advice;
	}

	public Object newProxyInstance(Object target) {

		this.target = target;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass()); // method not final
		enhancer.setCallback(this);
		return enhancer.create();
	}

	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
			throws Throwable {

		Object returnValue = null;

		if (advice.around(args[0])) {
			advice.before();

			try {
				returnValue = proxy.invoke(this.target, args);
//				returnValue = method.invoke(this.target, args);

				advice.afterReturn();
			}
			catch (RuntimeException e) {
//				e.printStackTrace();
				advice.afterException();
			}
			finally {
				advice.after();
			}

		}

		return returnValue;
	}

}
